/*
 * Copyright (c) 2020 Fraunhofer FOKUS and others. All rights reserved.
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contact: mosaic@fokus.fraunhofer.de
 */
package org.eclipse.mosaic.lib.transform;

import com.vividsolutions.jts.geom.Coordinate;
import org.eclipse.mosaic.lib.geo.MutableCartesianPoint;
import org.eclipse.mosaic.lib.geo.MutableGeoPoint;
import org.eclipse.mosaic.lib.geo.UtmPoint;
import org.eclipse.mosaic.lib.geo.UtmZone;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import org.osgeo.proj4j.BasicCoordinateTransform;
import org.osgeo.proj4j.CRSFactory;
import org.osgeo.proj4j.CoordinateReferenceSystem;
import org.osgeo.proj4j.ProjCoordinate;

@RunWith(MockitoJUnitRunner.class)
public class GeoTransformTest {

    private WictWgs84Projection utmProjection;

    private WictWgs84Projection projection;

    @Before
    public void initial() {
        UtmPoint utm = UtmPoint.eastNorth(
                UtmZone.from(new MutableGeoPoint(29.51771557134214, 106.3252472463716)),
                627760.02722,
                3265655.07925
        );
        utmProjection = new WictWgs84Projection(utm);
        MutableGeoPoint geoPoint = new MutableGeoPoint(29.51396724601234,
                106.31821950962147);
        projection = new WictWgs84Projection(geoPoint);
    }


    double longitude = 106.330088;
    double latitude = 29.518218;

    @Test
    public void testConvertToXY() {
        MutableGeoPoint point = new MutableGeoPoint(latitude, longitude);
        MutableCartesianPoint cartesian = new MutableCartesianPoint();

        utmProjection.geographicToCartesian(point, cartesian);
        System.out.println(cartesian);

        projection.geographicToCartesian(point, cartesian);
        System.out.println(cartesian);
    }

    private final static CRSFactory crsFactory = new CRSFactory();

    @Test
    public void geographicToXY() {
        Coordinate pt = new Coordinate(106.33003681839907, 29.518246002130212, 0);

        CoordinateReferenceSystem EPSGCRS = crsFactory.createFromName("EPSG:4326");
        CoordinateReferenceSystem WGS84CRS = crsFactory.createFromParameters("WGS84",
                "+proj=tmerc +lat_0=29.51396724601234 +lon_0=106.31821950962147 +k=1 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs");
        BasicCoordinateTransform transform = new BasicCoordinateTransform(EPSGCRS, WGS84CRS);
        ProjCoordinate pt1 = new ProjCoordinate(pt.x, pt.y, pt.z);
        ProjCoordinate pt2 = new ProjCoordinate();
        transform.transform(pt1, pt2);
        Coordinate coordinate = new Coordinate(pt2.x, pt2.y, pt2.z);
        System.out.println(coordinate);
    }

    @Test
    public void geographicToUTM() {
        Coordinate pt = new Coordinate(longitude, latitude);

        CoordinateReferenceSystem EPSGCRS = crsFactory.createFromName("EPSG:4326");
        CoordinateReferenceSystem WGS84UTMCRS = crsFactory.createFromParameters("WGS84",
                "+proj=utm +zone=48 +ellps=WGS84 +datum=WGS84 +no_defs");
        BasicCoordinateTransform transform = new BasicCoordinateTransform(EPSGCRS, WGS84UTMCRS);
        ProjCoordinate pt1 = new ProjCoordinate(pt.x, pt.y);
        ProjCoordinate pt2 = new ProjCoordinate();
        transform.transform(pt1, pt2);
        Coordinate coordinate = new Coordinate(pt2.x, pt2.y);
        System.out.println(coordinate);

        transform = new BasicCoordinateTransform(WGS84UTMCRS, EPSGCRS);
        pt1 = new ProjCoordinate(pt2.x, pt2.y);
        transform.transform(pt1, pt2);
        coordinate = new Coordinate(pt2.x, pt2.y);
        System.out.println(coordinate);
    }
}
